
/*
 * Searcher.java
 *
 * Created on October 20, 2007, 1:32 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
package com.afaker.searth.core.search;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
import java.util.logging.Level;
import org.apache.log4j.Logger;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.index.CorruptIndexException;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;

/**
 *
 * @author bruce
 */
public class Searcher {

    protected IndexSearcher search = null;
    protected IndexReader reader = null;
    protected QueryParser parser;
    private String path;
    private Properties properties;
    protected Hits hits;
    private String field = "content";
    private List stopFormat;
    protected static Logger log = Logger.getLogger(Searcher.class);

    /** Creates a new instance of Searcher */
    public Searcher() {
        properties = new Properties();
        stopFormat = new ArrayList();
        try {
            properties.load(
                    Searcher.class.getClassLoader().getResourceAsStream(
                    "index.properties"));
        } catch (IOException ex) {
            ex.printStackTrace();
        }
        path = properties.getProperty("index.dir");
    }

    public String getPath() {
        return path;
    }

    public void setPath(String path) {
        this.path = path;
    }

    public void addStopFormat(String format) {
        stopFormat.add(format);
    }

    public void clearStopFormat() {
        stopFormat.clear();
    }

    /**
     * Add Stop format to query object so that the the kind of format documents 
     * won't appear in the search results.
     * @param bool BoolQuery object
     */
    private void addStopFormatQuery(BooleanQuery bool) {
        Query q = null;
        QueryParser qparser = new QueryParser("format", new StandardAnalyzer());
        for (int i = 0; i < stopFormat.size(); i++) {
            try {
                q = qparser.parse((String) stopFormat.get(i));
            } catch (ParseException ex) {
                java.util.logging.Logger.getLogger(Searcher.class.getName()).log(Level.SEVERE, null, ex);
            }
            if (q != null) {
                bool.add(q, Occur.MUST_NOT);
            }
        }

    }

    /**
     * Search from Lucene's data file
     * @param query keywords you typed.
     * @param field The field in lucene that you want to search on.
     */
    public void search(String query, String field) {
        if (field != null || !field.trim().equals("")) {
            this.field = field;
        }
        File file = new File(path);
        if (file.listFiles() != null) {
            if (file.listFiles().length < 1) {
                return;
            }
        }
        try {
            reader = IndexReader.open(path);
        } catch (Exception ex) {
            log.error(ex.getClass(), ex);
            close();
            return;
        }
        search = new IndexSearcher(reader);
        parser = new QueryParser(this.field,
                new StandardAnalyzer());
        parser.setDefaultOperator(QueryParser.AND_OPERATOR);
        Query q = null;
        try {
            q = parser.parse(query);
        } catch (ParseException ex) {
            log.error(ex.getClass(), ex);
        }
        //Create bool query
        BooleanQuery bool = new BooleanQuery();
        bool.add(q, Occur.MUST);
        addStopFormatQuery(bool);
        try {
            log.info(bool.toString());
            hits = search.search(bool);
            //Clear this time's stop format so that next time won't cause confusion.
            clearStopFormat();
        } catch (IOException ex) {
            log.error(ex.getClass(), ex);
            close();
            return;
        }
    }

    public void close() {
        try {
            if (search != null) {
                search.close();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }

    public Hits getHits() {
        return hits;
    }

    public static void main(String[] args) {
        try {
            // TODO code application logic here
            /*Searcher s = new Searcher();
            s.search("java", "content");
            Hits h = s.getHits();
            for (int i = 0; i < h.length(); i++) {
            Document doc = null;
            try {
            doc = h.doc(i);
            } catch (CorruptIndexException ex) {
            ex.printStackTrace();
            } catch (IOException ex) {
            ex.printStackTrace();
            }
            System.out.println(doc.get("path"));
            }*/
            IndexReader reader = IndexReader.open("/home/bruce/Programming/Java/Searth/src/index");
            
            System.out.println(reader.numDocs());
            reader.close();
        } catch (CorruptIndexException ex) {
            java.util.logging.Logger.getLogger(Searcher.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IOException ex) {
            java.util.logging.Logger.getLogger(Searcher.class.getName()).log(Level.SEVERE, null, ex);
        }
        
    }
}
